<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../bower_components/paper-input/paper-input-error.html">
<link rel="import" href="../../bower_components/paper-input/paper-textarea.html">
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="../../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../../bower_components/vaadin-icons/vaadin-icons.html">

<link rel="import" href="../../bower_components/mist-list/mist-list-actions.html">
<link rel="import" href="../../bower_components/mist-list/mist-list-actions-behavior.html">

<link rel="import" href="../tags/tags-form.html">
<link rel="import" href="../helpers/xterm-dialog.html">
<link rel="import" href="../helpers/dialog-element.html">
<link rel="import" href="../helpers/transfer-ownership.html">
<link rel="import" href="../mist-icons.html">
<link rel="import" href="associate-key.html">
<link rel="import" href="run-script-on-machine.html">
<link rel="import" href="resize-dialog.html">
<link rel="import" href="machine-edit.html">
<link rel="import" href="attach-volume-on-machine.html">
<link rel="import" href="machine-snapshots.html">
<script type="text/javascript" src="../volume-create-fields.js" inline></script>
<dom-module id="machine-actions">
    <template>
        <style  include="shared-styles">
            mist-list-actions {
                width: 100%;
            }
        </style>
        <machine-edit id="renamedialog" items="[[items]]"></machine-edit>
        <run-script-on-machine id="runscriptdialog" items="[[items]]" scripts="[[model.scriptsArray]]"></run-script-on-machine>
        <associate-key id="associatekeydialog" items="[[items]]" model="[[model]]"></associate-key>
        <machine-snapshots id="snapshotdialog" machine="[[items.0]]" snapshots="" action=""></machine-snapshots>
        <attach-volume-on-machine id="attachvolumedialog" machine="[[items.0]]" model="[[model]]"></attach-volume-on-machine>
        <dialog-element id="confirm" fields="{{action.fields}}"></dialog-element>
        <tags-form id="tagsdialog" model="[[model]]" items=[[items]] type="machine"></tags-form>
        <transfer-ownership id="ownershipdialog" user="[[user]]" members="[[_otherMembers(model.membersArray,items.length)]]" items="[[items]]" type="[[type]]"></transfer-ownership>
        <resize-dialog id="resizedialog" machine="[[_getMachine(items.length)]]" clouds="[[model.clouds]]"></resize-dialog>
        <iron-ajax id="request" handle-as="json" loading="{{loadingData}}" on-response="handleResponse" on-error="handleError"></iron-ajax>
        <slot>
            <mist-list-actions actions=[[actions]]></mist-list-actions>
        </slot>
    </template>
    <script>
    const MACHINE_ACTIONS = {
        'attach-volume': {
            'name': 'attach volume',
            'icon': 'device:storage',
            'confirm': false,
            'multi': false,
            'single': true
        },
        'create_snapshot': {
            'name': 'create snapshot',
            'icon': 'image:add-a-photo',
            'confirm': true,
            'multi': false
        },
        'remove_snapshot': {
            'name': 'remove snapshot',
            'icon': 'image:monochrome-photos',
            'confirm': true,
            'multi': false
        },
        'revert_to_snapshot': {
            'name': 'revert to snapshot',
            'icon': 'social:party-mode',
            'confirm': true,
            'multi': false
        },
        'shell': {
            'name': 'shell',
            'icon': 'vaadin:terminal',
            'confirm': false,
            'multi': true
        },
        'console': {
            'name': 'console',
            'icon': 'vaadin:terminal',
            'confirm': false,
            'multi': true
        },
        'tag': {
            'name': 'tag',
            'icon': 'label',
            'confirm': true,
            'multi': true
        },
        'associate-key': {
            'name': 'associate key',
            'icon': 'communication:vpn-key',
            'confirm': true,
            'multi': true
        },
        'run-script': {
            'name': 'run script',
            'icon': 'image:movie-creation',
            'confirm': true,
            'multi': false
        },
        'reboot': {
            'name': 'reboot',
            'icon': 'av:replay',
            'confirm': true,
            'multi': true
        },
        'start': {
            'name': 'start',
            'icon': 'av:replay',
            'confirm': true,
            'multi': true
        },
        'stop': {
            'name': 'stop',
            'icon': 'av:stop',
            'confirm': true,
            'multi': true
        },
        'clone': {
            'name': 'clone',
            'icon': 'content-copy',
            'confirm': true,
            'multi': false,
            'fields': [{
                type: 'text',
                name: 'name',
                label: "Clone's Name",
                type: 'text',
                value: '',
                defaultValue: '',
                show: true,
                required: false,
            }]
        },
        'suspend': {
            'name': 'suspend',
            'icon': 'av:stop',
            'confirm': true,
            'multi': true
        },
        'rename': {
            'name': 'rename',
            'icon': 'editor:mode-edit',
            'confirm': true,
            'multi': false
        },
        'resize': {
            'name': 'resize',
            'icon': 'image:photo-size-select-small',
            'confirm': true,
            'multi': false
        },
        'resume': {
            'name': 'resume',
            'icon': 'av:replay',
            'confirm': true,
            'multi': true
        },
        'undefine': {
            'name': 'undefine',
            'icon': 'image:panorama-fish-eye',
            'confirm': true,
            'multi': true
        },
        'remove': {
            'name': 'remove',
            'icon': 'remove',
            'confirm': true,
            'multi': true
        },
        'destroy': {
            'name': 'destroy',
            'icon': 'delete',
            'confirm': true,
            'multi': true
        },
        'transfer-ownership': {
            'name': 'transfer ownership',
            'icon': 'icons:redo',
            'confirm': false,
            'multi': true
        },
        'tag': {
            'name': 'tag',
            'icon': 'label',
            'confirm': true,
            'multi': true
        },
        'webconfig': {
            'name': 'webconfig',
            'icon': 'mist-icons:menu',
            'confirm': true,
            'multi': false
        },
        'delete': {
            'name': 'delete',
            'icon': 'delete',
            'confirm': true,
            'multi': true
        }
    };

    Polymer({
        is: 'machine-actions',
        behaviors: [MistListActionsBehavior],
        properties: {
            model: {
                type: Object
            },
            items: {
                type: Array,
                value: function() {
                    return []
                }
            },
            actions: {
                type: Array,
                value: function() {
                    return []
                },
                notify: true
            },
            inSinglePage: {
                type: Boolean,
                value: false,
                reflectToAttribute: true
            },
            action: {
                type: Object
            },
            providersWithVolumes: {
                type: Array,
                value: function() {
                    return VOLUME_CREATE_FIELDS.map(i => i.provider);
                }
            },
        },
        listeners: {
            'rename-machine': 'renameAction',
            'transfer-ownership': 'transferOwnership',
            'perform-action': 'performAction',
            'confirmation': 'confirmAction',
            'select-action': 'selectAction',
        },
        ready: function() {},
        attached: function() {
            this.$.request.headers["Content-Type"] = 'application/json';
            this.$.request.headers["Csrf-Token"] = CSRF_TOKEN;
            this.$.request.method = "POST";
        },
        computeItemActions: function(machine) {
            var arr = [];
            if (this.model && this.model.clouds && ['vsphere', 'openstack'].indexOf(this.model.clouds[machine.cloud].provider) > -1){
                if(machine.state == "running"){
                arr.push('console');}}
            if (machine) {
                if (machine.os_type != 'windows' && machine.machine_type != 'ilo-host') {
                    arr.push('shell');
                    arr.push('associate-key');
                }
                if (this.inSinglePage && this.providersWithVolumes.indexOf(this.model.clouds[machine.cloud].provider) > -1) {
                    arr.push('attach-volume');
                }
            }
            if (machine && machine.actions) {
                for (var action in machine.actions) {
                    if (machine.actions[action])
                        arr.push(action);
                }
            }
            if (machine.key_associations && machine.key_associations.length) {
                arr.push('run-script');
            }
            if (this.model && this.model.org.ownership_enabled && (machine.owned_by == this.model.user.id || this.model.org.is_owner)) {
                arr.push('transfer-ownership');
            }
            return arr.sort(this._sortActions.bind(this));
        },
        _sortActions: function(a, b) {
            var sortOrder = [
                'console',
                'shell',
                'webconfig',
                'start',
                'stop',
                'clone',
                'suspend',
                'resume',
                'reboot',
                'resize',
                'undefine',
                'remove',
                'destroy',
                'delete',
                'attach-volume',
                'create_snapshot',
                'revert_to_snapshot',
                'remove_snapshot',
                'associate-key',
                'rename',
                'run-script',
                'transfer-ownership',
                'tag'
            ];
            if (sortOrder.indexOf(a) < sortOrder.indexOf(b)) {
                return -1;
            }
            if (sortOrder.indexOf(a) > sortOrder.indexOf(b)) {
                return 1;
            }
            // a must be equal to b
            return 0;
        },
        _otherMembers: function(members, items) {
            if (this.items && members) {
                var owners = this.items.map(function(i) { return i.owned_by; })
                    .filter(function(value, index, self) { return self.indexOf(value) === index; });
                // filter out pending users and the single owner of the item-set if that is the case
                return members.filter(function(m) {
                    return owners.length == 1 ? m.id != owners[0] && !m.pending : !m.pending;
                });
            }
        },
        _getMachine: function(length) {
            if (this.items.length)
                return this.get('items.0');
            else
                return undefined;
        },
        computeActionListDetails: function(actions) {
            var ret = [];
            for (var i = 0; i < actions.length; i++) {
                ret.push(MACHINE_ACTIONS[actions[i]]);
            }
            return ret;
        },
        _delete: function(items) {
            //set up iron ajax
            this.$.request.headers["Content-Type"] = 'application/json';
            this.$.request.headers["Csrf-Token"] = CSRF_TOKEN;
            this.$.request.method = "DELETE";

            for (var i = 0; i < this.items.length; i++) {
                this.$.request.url = "/api/v1/machines/" + this.items[i].id
                this.$.request.generateRequest();
                this.dispatchEvent(new CustomEvent('toast', { bubbles: true, composed: true, detail:  {
                    msg: 'Deleting ' + this.items[i].name,
                    duration: 1000
                } }))
            }
        },
        _showDialog: function(info) {
            var dialog = this.shadowRoot.querySelector('dialog-element');
            if (info) {
                for (var i in info) {
                    dialog[i] = info[i];
                }
            }
            dialog._openDialog();
        },
        selectAction: function(e) {
            console.log('selectAction machine-actions');
            if (this.items.length) {
                var action = e.detail.action;
                this.set('action', action);
                // console.log('perform action mist-action', this.items);
                if (action.confirm && ['tag', 'rename', 'run script', 'associate key', 'resize', 'webconfig', 'create snapshot', 'remove snapshot', 'revert to snapshot'].indexOf(action.name) ==
                    -1) {
                    var plural = this.items.length == 1 ? '' : 's',
                        count = this.items.length > 1 ? this.items.length + ' ' : '';
                    if (action.name == "clone" && this.action.fields) {
                        this.set('action.fields.0.value', this.items[0].value || this.items[0].name + "-clone");
                    }
                    this._showDialog({
                        title: this.action.name + ' ' + count + 'machine' + plural + '?',
                        body: "You are about to " + this.action.name + " " + this.items.length + " machine" +
                            plural + ".",
                        list: this._makeList(this.items, "name"),
                        action: action.name,
                        danger: true,
                        hideText: this.action.fields ? true : false,
                        reason: "machine." + this.action.name
                    });
                } else if (action.name == 'delete') {
                    this._delete(this.items);
                } else if (action.name == 'resize') {
                    this.$.resizedialog._openDialog();
                } else if (action.name == 'tag') {
                    this.$.tagsdialog._openDialog();
                } else if (action.name == 'attach volume') {
                    this.$.attachvolumedialog._openDialog();
                } else if (action.name == 'transfer ownership') {
                    this.$.ownershipdialog._openDialog();
                } else if (action.name == 'create snapshot') {
                    this.$['snapshotdialog'].action = action.name;
                    this.$['snapshotdialog']._openDialog();
                } else if (action.name == 'remove snapshot') {
                    this.$['snapshotdialog'].snapshots = this.items[0].extra.snapshots;
                    this.$['snapshotdialog'].action = action.name;
                    this.$['snapshotdialog']._openDialog();
                } else if (action.name == 'revert to snapshot') {
                    this.$['snapshotdialog'].snapshots = this.items[0].extra.snapshots;
                    this.$['snapshotdialog'].action = action.name;
                    this.$['snapshotdialog']._openDialog();
                } else if (action.name == 'rename') {
                    this.$['renamedialog']._openDialog();
                } else if (action.name == 'webconfig') {
                    this._openWebconfig(this.items);
                } else if (action.name == 'run script') {
                    this.$['runscriptdialog']._openDialog();
                } else if (action.name == 'associate key') {
                    this.$['associatekeydialog']._openDialog();
                } else if (!action.confirm) {
                    this.performMachineAction(action, this.items);
                }
            }
        },
        _openWebconfig: function(items) {
            var machine = this.items[0];
            var url = 'https://' + machine.hostname + ':81';
            window.open(url, "view");
        },
        confirmAction: function(e) {
            if (e.detail.confirmed)
                this.performMachineAction(this.action, this.items);
        },
        renameAction: function(e) {
            console.log('renameAction', e.detail);
            this.performMachineAction(e.detail.action, this.items, e.detail.name);
        },
        transferOwnership: function(e) {
            var payload = {
                user_id: e.detail.user_id, //new owner
                resources: {}
            };
            payload.resources['machine'] = this.items.map(function(i) { return i.id });
            console.log('transferOwnership', e.detail, payload);
            this.$.request.url = '/api/v1/ownership';
            this.$.request.headers["Content-Type"] = 'application/json';
            this.$.request.headers["Csrf-Token"] = CSRF_TOKEN;
            this.$.request.method = "POST";
            this.$.request.body = payload;
            this.$.request.generateRequest();
        },
        performMachineAction: function(action, items, name) {
            var runitems = items.slice();
            // console.log('perform action machine',items);
            var run = function(el) {
                var uri, payload, item = runitems.shift(),
                    method = 'POST';
                // console.log('renameAction', item.name, action.name, name);
                //machines
                if (action.name == 'shell') {
                    console.warn('opening shell');
                    // load page import on demand.
                    // el.importHref(el.resolveUrl('/elements/helpers/xterm-dialog.html'), null, null, true);
                    // remove existing terminals from DOM
                    var xterm = document.querySelector("xterm-dialog");
                    if (xterm) {
                        xterm.remove();
                        // console.log('xterm removed', this.items);
                    }

                    xterm = el.querySelector("xterm-dialog");
                    if (!xterm) {
                        xterm = document.createElement("xterm-dialog");
                        xterm.target = item;
                        var app = document.querySelector('mist-app');
                        app.shadowRoot.insertBefore(xterm, app.shadowRoot.firstChild);
                    }
                    // console.log('perform action shell', item);
                    return;
                } else if (['reboot', 'start', 'stop', 'suspend', 'resume', 'undefine', 'destroy', 'remove'].indexOf(action.name) >
                    -1) {
                    uri = '/api/v1/machines/' + item.id;
                    payload = {
                        'action': action.name
                    };
                } else if (action.name == 'rename') {
                    uri = '/api/v1/machines/' + item.id;
                    payload = {
                        'action': action.name,
                        'name': name
                    };
                } else if (action.name == 'clone') {
                    uri = '/api/v1/machines/' + item.id;
                    payload = {
                        'action': action.name,
                        'name': action.fields[0].value
                    };
                } else if (action.name == 'probe') {
                    uri = '/api/v1/machines/' + item.id + '/probe';
                    payload = {
                        'host': item.public_ips[0],
                        'key': item.key_associations[0]
                    };
                } else if (action.name == 'console') {
                    uri = '/api/v1/machines/' + item.id + '/console';
                    //window.open(uri, 'view');
                    var form = document.createElement("form");
                    form.setAttribute("method", "post");
                    form.setAttribute("action", uri);
                    form.setAttribute("target", "view");
                    var hiddenField = document.createElement("input");
                    hiddenField.setAttribute("type", "hidden");
                    hiddenField.setAttribute("name", "Csrf-Token");
                    hiddenField.setAttribute("value", CSRF_TOKEN);
                    form.appendChild(hiddenField);
                    document.body.appendChild(form);

                    window.open('', 'view');

                    form.submit();
                    return;
                } else if (action.name == 'transfer ownership') {
                    return;
                } else {
                    console.error('unknown action', action, 'on item', item);
                    return;
                }

                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function() {
                    if (xhr.readyState == XMLHttpRequest.DONE) {
                        var message = '';
                        if (xhr.status == 200) {
                            console.log(action, 'success');
                            message = 'Successfully ' + this.inPast(action.name) + ' machine. Updating...';
                            this.dispatchEvent(new CustomEvent('action-finished', { bubbles: true, composed: true, detail: {
                                success: true
                            } }));

                            // for machines destroy only and only if in machine page
                            var app_location = document.querySelector('app-location');
                            if (["destroy","remove"].indexOf(action.name) > -1 && document.location.pathname && document.location.pathname.split(
                                    '/machines/')[1] == item.id) {
                                // kvm machines
                                if (item.provider != 'kvm') {
                                    this.dispatchEvent(new CustomEvent('go-to', { bubbles: true, composed: true, detail: {
                                        url: '/machines'
                                    } }));

                                }
                            }
                            if (item.provider == 'kvm' && action.name == "undefine" && document.querySelector('app-location').path.split(
                                    '/machines/')[1] == item.id) {
                                this.dispatchEvent(new CustomEvent('go-to', { bubbles: true, composed: true, detail: {
                                    url: '/machines'
                                } }));

                            }
                        } else {
                            console.error(action, 'failed');
                            console.log(xhr);
                            var responsetext = xhr.responseText ? xhr.responseText : '';
                            message = action.name.toUpperCase() + ' failed.' + responsetext;
                            this.dispatchEvent(new CustomEvent('action-finished', { bubbles: true, composed: true, detail: {
                                success: false
                            } }));

                        }
                        this.dispatchEvent(new CustomEvent('toast', { bubbles: true, composed: true, detail: {
                            msg: message,
                            duration: 5000
                        } }));

                        if (runitems.length) {
                            run(el);
                        } else {
                            this.dispatchEvent(new CustomEvent('action-finished'));



                        }
                    }
                }.bind(this);

                xhr.open(method, uri);
                xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
                xhr.setRequestHeader("Csrf-Token", CSRF_TOKEN);
                xhr.send(JSON.stringify(payload));

                var logMessage = 'Performing action ' + action.name.toUpperCase() + ' on machine ' + this.model.machines[
                    item.id].name;
                this.dispatchEvent(new CustomEvent('performing-action', { bubbles: true, composed: true, detail: {
                    log: logMessage
                } }));

            }.bind(this);

            run(this);
        },
        handleResponse: function(e) {
            console.log('handle response', e, this.$.request.body);
            if (this.$.request && this.$.request.body && this.$.request.body.action)
                this.dispatchEvent(new CustomEvent('toast', { bubbles: true, composed: true, detail: {
                    msg: 'Action: ' + (this.$.request.body.action || 'ownership transfer') + ' successfull',
                    duration: 3000
                } }));

            if (e.detail.xhr.responseURL.endsWith("api/v1/ownership") && e.detail.xhr.status == 200) {
                this.$.ownershipdialog._closeDialog();
                this.dispatchEvent(new CustomEvent('action-finished'));
                
                if (this.querySelector('mist-list-actions')) {
                    this.querySelector('mist-list-actions').fire('action-finished');
                }

                this.dispatchEvent(new CustomEvent('toast', { bubbles: true, composed: true, detail: {
                    msg: 'Successfull ownership transfer',
                    duration: 3000
                } }));

            }
        },
        handleError: function(e) {
            // console.log(e.detail.request.xhr.statusText);
            this.dispatchEvent(new CustomEvent('toast', { bubbles: true, composed: true, detail: {
                msg: 'Error: ' + e.detail.request.xhr.status + " " + e.detail.request.xhr.statusText,
                duration: 5000
            } }));

            if (e.detail.request.xhr.responseURL.endsWith("api/v1/ownership")) {
                this.$.ownershipdialog._closeDialog();
            }
        },
        _makeList: function(items, property) {
            if (items && items.length)
                return items.map(function(item) {
                    return item[property];
                });
        },
        inPast: function(action) {
            if (action == 'shell')
                return 'opened shell'
            else if (action == 'tag')
                return 'tagged'
            else if (action == 'associate key')
                return 'associated key'
            else if (action == 'run-script')
                return 'run script'
            else if (action == 'reboot')
                return 'rebooted'
            else if (action == 'start')
                return 'started'
            else if (action == 'stop')
                return 'stopped'
            else if (action == 'suspend')
                return 'suspended'
            else if (action == 'rename')
                return 'renamed'
            else if (action == 'resume')
                return 'resumed'
            else if (action == 'clone')
                return 'cloned'
            else if (action == 'undefine')
                return 'undefined'
            else if (action == 'suspend')
                return 'suspended'
            else if (action == 'destroy')
                return 'destroyed'
            else if (action == 'remove')
                return 'removed'
            else if (action == 'star')
                return 'starred'
            else if (action == 'unstar')
                return 'unstarred'
            else if (action == 'destroy')
                return 'destroyed'
            else if (action == 'make default')
                return 'made default'
            else if (action == 'run')
                return 'run'
            else if (action == 'enable')
                return 'enabled'
            else if (action == 'disable')
                return 'disabled'
            else if (action == 'disable')
                return 'disabled'
            else if (action == 'delete')
                return 'deleted'
            else
                return ''
        }
    });
    </script>
</dom-module>
